旋轉跳躍
還正在想
在寫 app 的時候,生命週期是一件很重要的事情!
什麼是生命週期呢?簡單來講就是一個 app 的生老病死。有可能在用這個 app 用到一半的時候,突然想去滑個 FB,或是想去打個電話,這時候會離開這個 app 而跳到其他地方,在生命週期裡就是該 app 會被 onDestroy() 掉,等到再次執行時,會再 onCreate() 出來!當然啦~在這個例子只提到了 2 個狀態,真正的生命週期可是相當複雜的呢~
相當建議想要認識這部分的朋友,去對每個階段都 override 出來,並且把他們印出來(Log.d()),去觀察每個階段的先後順序,會更有概念唷!
相較於掌握自己人生不可預知的週期,掌握 android 的 app 相對容易許多
沒處理生命週期

由上述發現,奇怪,怎麼旋轉個螢幕回來,一切都不一樣了QQ原本的資料都被清掉了?在旋轉螢幕的時候,整個 app 會把 Activity 給清掉,並且產生一個橫向新的 Activity,跟我們原先以為單純的旋轉可不一樣呢!而在探討生命週期,又會區分 Activity 的或者是 Fragement 的,可以參考下圖唷!
Fragment 和 Activity 生命週期圖

上圖可以看到,相較於 Activity,Fragment 的人生階段分得更為精細,而這張對比圖則是大致上去相互呼應兩者相同的階段。
小筆記
onCreate() 到呈現畫面的 running 狀態,如果有要離開目前的畫面,則有可能進入臨死之前的遺言狀態(我自己為了好記亂取的...) onSaveInstance(),這邊可以在被 onDestroy() 之前,把該存好的存好,把該交代好的都先說好,然後離開QQ當下次回來時,會去檢查是否有曾經遺留保存下來的 Bundle 資料 (savedInstanceState),並且對他做使用唷!這邊的 "回來",或是 "重生",的意思又有分做 onResume 、 onCreateView 的不同階段,端看你怎麼死去的(可以從圖上清楚看出對應的關係)建立界面
這邊我建立了一個 EditText 、TextView 以及一個 ImageButton,為的是在 EditText 輸入字串之後,按下 ImageButton ==字串會顯示在 TextView==,接著我做旋轉螢幕的動作,如果沒有特別在生命週期的階段做處理,會因為 onDestroy() 的關係,==TextView 的字串會消失==
臨走前,交代 onSaveInstanceState()
現在我們都知道了,在 onDestroy() 之後,所有原本的資料都會被清空,但我希望我再次回來時,資料還能保存起來,該怎辦?在翻轉手機,準備進入 onDestroy() 之前,會先進入 onSaveInstanceState() 階段,我們必須把要保存的資料,先塞進去一個叫做 outState 的 Bundle 裡面,確定塞好之後,就可以安心的去了。這邊需要對這比資料加入一個 key 值,之後如果要再取出資料,就必須靠這筆 key 值才找得回來唷
override fun onSaveInstanceState(outState: Bundle) {
Log.d("state", "onSaveInstanceState")
outState.putString(SPIN_KEY, show_input?.text.toString())
super.onSaveInstanceState(outState)
}
甦醒!怎麼取之前保存好的值呢?
在這邊我們使用了 onActivityCreated() ,當他的參數 savedInstanceState() 有原先指定的 key 值,表示找得到資料,如果是空的(譬如第一次開啟這個 app),那就沒資料而不做任何動作。在 onCreateView() 之後會進到這個階段,如果有取到 key 值的話,就可以把這個值給送回去給原本的主人(在這邊是 TextView ),一切就像是一直都沒離開過囉!
override fun onActivityCreated(savedInstanceState: Bundle?) {
super.onActivityCreated(savedInstanceState)
Log.d("state", "onActivityCreated")
val spinValue = savedInstanceState?.getString(SPIN_KEY)
if(spinValue != null){
show_input.text = spinValue
Log.d("restore data", spinValue)
}
}
不會進 onSaveInstance() ?
在旋轉螢幕的時候,都會經過 onSaveInstance(),但是在實驗切換 Fragment 時,怎麼跟想像的不一樣呢?後來才之後,onSaveInstance() 只有在 Activity 發生要 onDestroy 時才有作用,而這邊的是 Fragment 要離開了,但是原先的 Activity 還活得好好的,當然不會進去囉
onSaveInstance() 不會存值?
這個坑是之前卡蠻久的,後來才知道自己 override 到另一個 function,叫做 onSaveInstanceState(outState: Bundle?, outPersistentState: PersistableBundle?) 。這個是給 app.Activity 用的,而自己卻是 app.AppCompatActivity,所以應該用的是 onSaveInstanceState(outState: Bundle?) 才對喲!後來查了一下,PersistableBundle 似乎是用在當 reboot 之後要去拿取 data 的,但是怎麼實際運用也沒多研究就是了